﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Rel.Expressions
{
    public class RelGroup
    {

        internal bool UseExtractGroup = true;

        private static int StartingNodeNumber=0;

        public int CurrentNodeNumber { get { return rGroupNodeNumber; } }
 
        public class GroupSearchResult
        {
            public string Name;

            public enum ResultType { RelGroup, BaseResult };

            public ResultType Type;

            public RegBase BaseResult;
            public RelGroup RelResult;
        }

        public GroupSearchResult FindGroup(string name)
        {
            if ( name == this.GroupName)
            {
                return new GroupSearchResult() { BaseResult = null, RelResult = this, Type = GroupSearchResult.ResultType.RelGroup, Name = name };
            }
            else
            {
                foreach (RegBase r in RegexChain)
                {
                    if ( r.GroupName.Equals(name))
                    {
                        return new GroupSearchResult() { BaseResult = r, RelResult = null, Type = GroupSearchResult.ResultType.BaseResult, Name = name };
                    }
                    else
                    {
                        foreach (RelGroup o in r.ChildExpressions)
                        {
                            GroupSearchResult g = o.FindGroup(name);
                            if (g != null) { return g; }
                        }
                    }

                }

                return null;
            }
        }

        public void ClearGroupNames()
        {
            RegexChain.ForEach(o => o.UseExtract = false);
        }

        public string Pattern
        {
            get
            {
                if ( RegexChain.Count == 0) return string.Empty;


                if (UseExtractGroup)
                {
                    string pattern = "(?<" + GroupName + ">(";

                    for (int x = 0; x < RegexChain.Count; x++)
                    {
                        pattern += RegexChain[x].Pattern;
                    }
                    pattern += "))";

                    return pattern;
                }
                else
                {

                    string pattern = "(";

                    for (int x = 0; x < RegexChain.Count; x++)
                    {
                        pattern += RegexChain[x].Pattern;
                    }
                    pattern += ")";

                    return pattern;

                }
            }
        }

        public string GroupName
        {
            get { return (UseExtractGroup? "ExGroup" + rGroupNodeNumber.ToString() + "_0":string.Empty); }
        }

        public int GroupNodeNumber
        {
            get { return rGroupNodeNumber; }
            set
            {
                rGroupNodeNumber = value;
            }
        }

        public int CurrentRegBaseNodeNumber { get { return currRegbaseNodeNumber; } }



        private int rGroupNodeNumber;
        private int currRegbaseNodeNumber;


        /// <summary>
        ///  Called by Regbase to insert new expressions into the regular expression chain.
        ///  Never to be called outside this context.
        /// </summary>
        /// <param name="item"></param>
        /// <param name="withGroup"></param>
        internal void Add(RegBase item)
        {
            RegexChain.Add(item);

            item.ChainNumber = currRegbaseNodeNumber;
            
            currRegbaseNodeNumber++;
        }

        protected List<RegBase> RegexChain = new List<RegBase>();

        /// <summary>
        /// Execute patterns against this member to create expression chains.
        /// </summary>
        public StartClass Starter
        {
            get { return starter; }
        }

        protected StartClass starter;

        public RelGroup(RelGroup parent  )
        {
            starter = new StartClass(this);

            rGroupNodeNumber = RelGroup.StartingNodeNumber++;
          
            currRegbaseNodeNumber = 1;
            }

        public RelGroup()
        {
      
            starter = new StartClass(this);

            rGroupNodeNumber = RelGroup.StartingNodeNumber++;
   
            currRegbaseNodeNumber = 1;
        }

        public int Count { get { return RegexChain.Count; } }

       
    }
}
